package com.mlnx.work.service.iml;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mlnx.common.form.PageForm;
import com.mlnx.work.cache.CacheKeys;
import com.mlnx.work.dao.mysql.UserMapper;
import com.mlnx.work.entity.User;
import com.mlnx.work.enums.AccountStatusEnum;
import com.mlnx.work.enums.ResponseEnum;
import com.mlnx.work.exception.WorkServiceException;
import com.mlnx.work.pojo.dto.UserRightDto;
import com.mlnx.work.pojo.form.UserFilterForm;
import com.mlnx.work.pojo.form.UserFindPassForm;
import com.mlnx.work.pojo.form.UserForm;
import com.mlnx.work.pojo.form.UserRegisterForm;
import com.mlnx.work.service.DepartmentService;
import com.mlnx.work.service.MailService;
import com.mlnx.work.service.UserRoleService;
import com.mlnx.work.service.UserService;

import org.shan.spring.cache.CacheObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;

import cn.hutool.core.bean.BeanUtil;

/**
 * author name: amanda.shan
 * create time: 2020-12-28 16:58:01
 */
@Service
public class UserServiceIml extends BaseService<UserMapper, User> implements UserService {

    @Autowired(required = false)
    private PasswordEncoder encoder;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private MailService mailService;

    @PostConstruct
    public void init(){
        userService = this;
    }

    @Autowired
    @Override
    public void setBaseMapper(UserMapper baseMapper) {
        super.setBaseMapper(baseMapper);
        userMapper = baseMapper;
    }


    @Override
    public void save(User entity) {
        super.save(entity);
    }

    @Override
    public IPage page(PageForm pageForm, Object filter) throws IllegalAccessException {
        return baseMapper.listUserVo(new Page<>(pageForm.getCurrent(), pageForm.getSize()), (UserFilterForm) filter);
    }

    @Override
    public List<User> listAll(Object filter) throws IllegalAccessException {
        QueryWrapper<User> wrapper = this.getQueryWrapper(filter);
        wrapper.select("id", "name");
        List list = this.list(wrapper);
        return list;
    }

    @Transactional
    @Override
    public void register(UserRegisterForm registerForm) {

        User user = new User();

        Integer count = baseMapper.selectCount(new QueryWrapper<User>().eq(
                "username", registerForm.getUsername()));
        if (count != null && count > 0) {
            throw new WorkServiceException(ResponseEnum.USER_FAIL.getCode(), "邮箱已经存在");
        }

        if (!checkEmailCode(registerForm.getUsername(), registerForm.getCode())) {
            throw new WorkServiceException(ResponseEnum.USER_FAIL.getCode(), "验证码错误");
        }

        // 保持账户
        BeanUtil.copyProperties(registerForm, user);
        user.setPswd(encoder.encode(registerForm.getPswd()));
        user.setStatus(AccountStatusEnum.NOT);
        user.setRegisterTime(new Date());
        baseMapper.insert(user);

        if (user.getDeptId() != null) {
            departmentService.renewCount(user.getDeptId(), getDeptCount(user.getDeptId()));
        }

        log.info("用户注册成功:{}", registerForm);
    }

    @Override
    public User getById(Serializable id) {
        User user = super.getById(id);
        user.setPswd(null);
        return user;
    }

    @Override
    public String getEmailCode(String email) {
        String[] chars = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
        String msgCode = "";
        Random ran = new Random();
        for (int i = 0; i < 6; i++) {
            int num = ran.nextInt(chars.length);
            msgCode += chars[num];
        }

//		String templateCode = "SMS_176600469";
//		SmsUtils.sendSms(templateCode, phone, msgCode);

        mailService.sendMailCode(email, msgCode);

        log.info("保存验证码:{}", msgCode);
        cacheChannel.set(CacheKeys.CODE_KEY, email, msgCode);

        return msgCode;
    }

    @Transactional
    @Override
    public void updateById(Integer userId, UserForm userForm) {


        if (userForm.getRoleIds() != null) {
            userRoleService.changeUserRole(userId, userForm.getRoleIds());
        }

        if (userForm.getDeptId() != null) {
            departmentService.renewCount(userForm.getDeptId(), getDeptCount(userForm.getDeptId()));
        }

        User user = new User();
        BeanUtil.copyProperties(userForm, user);

        if (!BeanUtil.isEmpty(user)) {
            user.setId(userId);
            updateById(user);
        }
    }

    @Override
    public UserRightDto getUserRoleDto(String username) {
        return baseMapper.selectUserRightDto(username);
    }

    @Override
    public void findPas(UserFindPassForm userFindPassForm) {
        if (!checkEmailCode(userFindPassForm.getUsername(), userFindPassForm.getCode())) {
            throw new WorkServiceException(ResponseEnum.USER_FAIL.getCode(), "验证码错误");
        }

        User user = new User();

        // 保持账户
        user.setPswd(encoder.encode(userFindPassForm.getPswd()));

        baseMapper.update(user, new QueryWrapper<User>().eq("username", userFindPassForm.getUsername()));

    }

    public boolean checkEmailCode(String phone, String code) {

        code = code.trim();
        log.info("校验验证码:{}", code);
        CacheObject cacheObject = cacheChannel.get(CacheKeys.CODE_KEY, phone, false);

        Object rawValue = cacheObject.rawValue();
        if (rawValue != null && rawValue.toString().equals(code)) {
            evict(CacheKeys.CODE_KEY, phone);
            return true;
        }

        return false;
    }

    private Integer getDeptCount(Integer deptId) {
        return count(new QueryWrapper<User>().eq("dept_id", deptId));
    }

}

